home *** CD-ROM | disk | FTP | other *** search
- /*
- * multires.c
- *
- * Practical Algorithms for Image Analysis
- *
- * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
- */
-
- /* MULTIRES: program performs image subsampling after low-pass filtering
- * to produce multiresolution pyramid of images subsampled
- * by 2. These are displayed in the original image area.
- * usage: multires inimg outimg [-c || -m || -l LEVEL]
- * [-d DEGREE_FILTERING] [-q quickFlag] [-L]
- */
-
- #define OUTTYPE_DFLT 1 /* =1 composite image; =2 multiple; =3 single level */
- #define BGFLAG_DFLT 0 /* background flag for composite =0 blank; =1 orig. */
- #define SUBRATE 2 /* subsample rate between levels */
- #define DFLT_DEG_FLTR 0.5 /* default degree of filtering */
- #define RECT_CUTOFF 0.443883 /* factor to calc. 3dB cutoff freq */
- #define GAUSS_CUTOFF 0.832555 /* factor to calc. 3dB cutoff freq */
- #define ROUNDUP 0.99999 /* for rounding up integer */
- #define NORM 1000.0 /* normaliz. factor to integerize */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <images.h>
- #include <tiffimage.h>
- #include <math.h>
- #include <string.h>
- extern void print_sos_lic ();
-
- long convolve1r (Image *, Image *, long *, long, long);
- long smoothr (Image *, Image *, long, long);
- long input (int, char **, short *, long *, short *, double *, short *);
- long usage (short);
-
- main (argc, argv)
- int argc;
- char *argv[];
- {
- Image *imgI, *imgO; /* input, output image structures */
- Image *imgT; /* intermediate image structure */
- unsigned char **imgIn, **imgOut; /* input, output image arrays */
- unsigned char **imgTi; /* intermediate image array */
- char outFile[80]; /* output filenames, multipe levels */
- long width, height; /* image size */
- double cutoff; /* low-pass cutoff frequency */
- long fltrSize; /* filter mask size */
- short outType; /* =1 composite image; =2 multiple; =3 single level */
- long outLevel; /* for single level output, specifies which level */
- short bgFlag; /* background flag for composite =0 blank; =1 orig. */
- double degFltr; /* degree of filtering [0.0 - 1.0] */
- double stdDev; /* std. deviation param. of Gaussian */
- long *fltr; /* 1D filter mask */
- long midFltr; /* middle filter coefficient */
- long widthR, heightR; /* subsampled image sizes */
- short quickFlag; /* for quick and dirty rect. filter */
- long xOffSet; /* x offset for pyramid display */
- long x, xO, y, i;
-
- if (input (argc, argv, &outType, &outLevel, &bgFlag,
- °Fltr, &quickFlag) < 0)
- return (-1);
-
- /* open input image */
- imgI = ImageIn (argv[1]);
- imgIn = ImageGetPtr (imgI);
- height = ImageGetHeight (imgI);
- width = ImageGetWidth (imgI);
- printf ("Image size is %dx%d.\n", width, height);
-
- /* determine filter size and coefficients */
- if (degFltr == 0.0)
- cutoff = 100.0;
- else
- cutoff = 0.5 / (SUBRATE * degFltr);
- if (quickFlag) /* rectangular filter window */
- fltrSize = (long) (RECT_CUTOFF / cutoff + ROUNDUP);
- else { /* Gaussian filter window */
- stdDev = GAUSS_CUTOFF / cutoff;
- fltrSize = (long) (3.0 / (2.0 * cutoff) + 0.5);
- }
- if ((fltrSize % 2) == 0)
- fltrSize += 1;
- printf ("Filter 3dB cutoff frequency is %5.2f and filter size is %dx%d.\n",
- cutoff, fltrSize, fltrSize);
-
- if (!quickFlag) {
- fltr = (long *) calloc (fltrSize, sizeof (*fltr));
- midFltr = fltrSize / 2;
- for (i = 0; i <= midFltr; i++)
- fltr[i + midFltr] = fltr[midFltr - i]
- = (long) (NORM * exp (-i * i / (2.0 * stdDev * stdDev)));
- }
-
- /* construct multi-resolution pyramid */
- heightR = height;
- widthR = width;
- imgT = ImageAlloc (height, width, 8);
- imgTi = ImageGetPtr (imgT);
- imgO = ImageAlloc (heightR, widthR, 8);
- imgOut = ImageGetPtr (imgO);
- xOffSet = 0;
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- imgTi[y][x] = imgIn[y][x];
- if (outType == 1 && bgFlag == 0) {
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- imgIn[y][x] = 0;
- }
- for (i = 1; (heightR >= 4 && widthR >= 4); i++) {
- if (quickFlag)
- smoothr (imgT, imgO, fltrSize, SUBRATE);
- else
- convolve1r (imgT, imgO, fltr, fltrSize, SUBRATE);
- heightR = heightR / SUBRATE;
- widthR = widthR / SUBRATE;
- printf ("level %d: %dx%d\n", i, heightR, widthR);
- ImageFree (imgT);
- imgT = ImageAlloc (heightR, widthR, 8);
- imgTi = ImageGetPtr (imgT);
- for (y = 0; y < heightR; y++)
- for (x = 0, xO = xOffSet; x < widthR; x++, xO++)
- imgIn[y][xO] = imgTi[y][x] = imgOut[y][x];
- if (outType == 2) { /* multiple level output images */
- sprintf (outFile, "m%d_%s", i, argv[2]);
- printf ("filename is %s\n", outFile);
- ImageOut (outFile, imgT); /* this is a hack -- flipBits in */
- // ImageOut (outFile, imgT); /* tiffimage.c causes inversion */
- }
- else if (i == outLevel) { /* single level output image */
- ImageOut (argv[2], imgT);
- exit (1);
- }
- xOffSet += widthR;
- }
-
- /* output subsampled image */
- ImageOut (argv[2], imgI);
-
- return (0);
- }
-
-
-
- /* SMOOTHR: function performs 2-D smoothing by separable, 1-D averaging
- * and returns subsampled image
- * usage: smoothr (imgI, imgO, nFltr, rSubsample)
- */
-
- long
- smoothr (imgI, imgO, nFltr, rSubsample)
- Image *imgI, *imgO; /* input,output image structures */
- long nFltr; /* number of filter coefficients */
- long rSubsample; /* subsample rate */
- {
- Image *imgT; /* intermediate image structure */
- unsigned char **imgIn, /* input image */
- **imgTi, /* intermediate image */
- **imgOut; /* output image */
- long width, height; /* size of image */
- long sum; /* sum of filter convolution at a pixel */
- long midFltr; /* middle coefficient index of filter */
- long xEnd, yEnd; /* end coefficients of convolution */
- long xOut, yOut; /* output image coordinates */
- long x, y, i;
-
- /* initialize images */
- imgIn = ImageGetPtr (imgI); /* input image */
- height = ImageGetHeight (imgI);
- width = ImageGetWidth (imgI);
- imgT = ImageAlloc (height, width, 8); /* intermediate image */
- imgTi = ImageGetPtr (imgT);
- imgOut = ImageGetPtr (imgO); /* output image */
-
- /* perform row-wise smoothing */
- midFltr = (nFltr - 1) / 2;
- xEnd = width - midFltr;
- for (y = 0; y < height; y++) {
- for (x = midFltr; x < xEnd; x += rSubsample) {
- sum = imgIn[y][x];
- for (i = 1; i <= midFltr; i++)
- sum += (long) (imgIn[y][x - i] + imgIn[y][x + i]);
- imgTi[y][x] = (unsigned char) (sum / nFltr);
- }
- }
-
- /* perform column-wise convolution */
- yEnd = height - midFltr;
- for (y = midFltr, yOut = 0; y < yEnd; y += rSubsample) {
- for (x = midFltr, xOut = 0; x < xEnd; x += rSubsample) {
- sum = imgTi[y][x];
- for (i = 1; i <= midFltr; i++)
- sum += imgTi[y - i][x] + imgTi[y + i][x];
- imgOut[yOut][xOut++] = (unsigned char) (sum / nFltr);
- }
- yOut++;
- }
-
- return (0);
- }
-
-
-
- /* CONVOLVE1R: function performs 2-D convolution by separable,
- * symmetric, 1-D filter mask, then outputs subsample image
- * usage: convolve1r (imgI, imgO, fltr1D, nFltr)
- */
-
- long
- convolve1r (imgI, imgO, fltr1D, nFltr, rSubsample)
- Image *imgI; /* input image structure */
- Image *imgO; /* output image structure */
- long *fltr1D; /* 1-D of filter mask */
- long nFltr; /* number of filter coefficients */
- long rSubsample; /* subsample rate */
- {
- Image *imgT; /* intermediate image structure */
- unsigned char **imgIn, /* input image */
- **imgTi, /* intermediate image */
- **imgOut; /* output image */
- long width, height; /* size of image */
- long sumFltr; /* sum of fltr coefficients */
- long sum; /* sum of filter convolution at a pixel */
- long midFltr; /* middle coefficient index of filter */
- long xEnd, yEnd; /* end coefficients of convolution */
- long xOut, yOut; /* output image coordinates */
- long x, y, i;
-
- /* initialize images */
- imgIn = ImageGetPtr (imgI);
- height = ImageGetHeight (imgI);
- width = ImageGetWidth (imgI);
- imgT = ImageAlloc (height, width, 8);
- imgTi = ImageGetPtr (imgT);
- imgOut = ImageGetPtr (imgO);
-
- /* find sum of filter coefficients */
- for (i = 0, sumFltr = 0; i < nFltr; i++)
- sumFltr += fltr1D[i];
-
- /* perform row-wise convolution */
- midFltr = (nFltr - 1) / 2;
- xEnd = width - midFltr;
- for (y = 0; y < height; y++) {
- for (x = midFltr; x < xEnd; x += rSubsample) {
- sum = fltr1D[midFltr] * imgIn[y][x];
- for (i = 1; i <= midFltr; i++)
- sum += fltr1D[i + midFltr]
- * (imgIn[y][x - i] + imgIn[y][x + i]);
- imgTi[y][x] = (unsigned char) (sum / sumFltr);
- }
- }
-
- /* perform column-wise convolution */
- yEnd = height - midFltr;
- for (y = midFltr, yOut = 0; y < yEnd; y += rSubsample) {
- for (x = midFltr, xOut = 0; x < xEnd; x += rSubsample) {
- sum = fltr1D[midFltr] * imgTi[y][x];
- for (i = 1; i <= midFltr; i++)
- sum += fltr1D[i + midFltr] * (imgTi[y - i][x] + imgTi[y + i][x]);
- imgOut[yOut][xOut++] = (unsigned char) (sum / sumFltr);
- }
- yOut++;
- }
-
- return (0);
- }
-
-
-
- /* USAGE: function gives instructions on usage of program
- * usage: usage (flag)
- * When flag is 1, the long message is given, 0 gives short.
- */
-
- long
- usage (flag)
- short flag; /* flag =1 for long message; =0 for short message */
- {
-
- printf ("USAGE: multires inimg outimg [<-c> || <-m> || <-l LEVEL>]\n");
- printf (" [-b] [-d DEG_FILTERING <%3.1f>] [-q] [-L]\n", DFLT_DEG_FLTR);
- if (flag == 0)
- return (-1);
-
- printf ("\nmultires performs multi-resolution processing upon an image\n");
- printf ("ARGUMENTS:\n");
- printf (" inimg: input image filename (TIF)\n");
- printf (" outimg: output image filename (TIF)\n\n");
- printf ("OPTIONS:\n");
- printf (" -c: composite image output of all multi-resolution levels\n");
- printf (" arranged in a single image; this is the default mode.\n");
- printf (" -m: multiple images of each multi-resolution level\n");
- printf (" in separate output image files; the output files are\n");
- printf (" m1_outimg.tif, m2_outimg.tif, ... for each level 1, 2, etc.\n");
- printf (" -l LEVEL: output is single image of the multi-resolution\n");
- printf (" level specified; level 1 is half size of original, level 2\n");
- printf (" is half size of level 1, etc; filename is output\n");
- printf (" filename specified, with 1, 2, etc. appended.\n");
- printf (" NOTE: only one of -c, -m, or -l should be chosen.\n");
- printf (" -b: BACKGROUND_FLAG for composite image <-c>; if flag is\n");
- printf (" set, then background to composite images is original image;\n");
- printf (" otherwise, the default is a blank background\n");
- printf (" of the original image size.\n");
- printf (" -d DEG_FILTERING: value set between 0.0 and 1.0 controlling\n");
- printf (" the degree of low-pass filtering; a value\n");
- printf (" of 1.0 produces maximum filtering to reduce aliasing,\n");
- printf (" but may lead to blurring;\n");
- printf (" a value of 0.0 does no filtering at the risk of aliasing.\n");
- printf (" the default is %3.1f.\n", DFLT_DEG_FLTR);
- printf (" -q: when set, performs quick low-pass filtering \n");
- printf (" with rectangular filter rather than Gaussian filter;\n");
- printf (" the former is faster but doesn't produce equally\n");
- printf (" good results as does the latter.\n");
- printf (" -L: print Software License for this module\n");
-
-
- return (-1);
- }
-
-
- /* INPUT: function reads input parameters
- * usage: input (argc, argv, &outType, &outLevel, &bgFlag,
- * °Fltr, &quickFlag)
- */
-
- #define USAGE_EXIT(VALUE) {usage (VALUE); return (-1);}
-
- long
- input (argc, argv, outType, outLevel, bgFlag, degFltr, quickFlag)
- int argc;
- char *argv[];
- short *outType; /* =1 composite image; =2 multiple; =3 single level */
- long *outLevel; /* for single level output, specifies which level */
- short *bgFlag; /* background flag for composite =0 blank; =1 orig. */
- double *degFltr; /* degree of filtering [0.0 - 1.0] */
- short *quickFlag; /* for quick and dirty rect. filter */
- {
- long n;
-
- if (argc < 3)
- USAGE_EXIT (1);
-
- *outType = OUTTYPE_DFLT;
- *outLevel = 0;
- *bgFlag = BGFLAG_DFLT;
- *degFltr = DFLT_DEG_FLTR;
- *quickFlag = 0;
-
- for (n = 3; n < argc; n++) {
- if (strcmp (argv[n], "-c") == 0)
- *outType = 1;
- else if (strcmp (argv[n], "-m") == 0)
- *outType = 2;
- else if (strcmp (argv[n], "-l") == 0) {
- if (++n == argc || argv[n][0] == '-')
- USAGE_EXIT (0);
- *outLevel = atol (argv[n]);
- *outType = 3;
- }
- else if (strcmp (argv[n], "-b") == 0)
- *bgFlag = 1;
- else if (strcmp (argv[n], "-d") == 0) {
- if (++n == argc || argv[n][0] == '-')
- USAGE_EXIT (0);
- *degFltr = atof (argv[n]);
- }
- else if (strcmp (argv[n], "-q") == 0)
- *quickFlag = 1;
- else if (strcmp (argv[n], "-L") == 0) {
- print_sos_lic ();
- exit (0);
- }
- else
- USAGE_EXIT (0);
- }
-
- return (0);
- }
-